/**
 * Url操作模块
 * @module utils/url
 * @author 耿朝继
 */

import { pathToRegexp } from 'path-to-regexp';

const hostRegex = /^(http|https):\/\/[\w.:]*\//;

/**
 * 是否为外链地址
 * @param {string} path
 * @returns {Boolean}
 */
export function isExternal(path) {
	return /^(https?:|mailto:|tel:)/.test(path);
}

/**
 * 参数字符串转换成对象形式，如：a=1&b=2 转换成 {a:1, b:2}
 * @param {String} str 需要转换的字符串
 * @param {String} [sep=&] 连接符，可选，默认 &
 * @param {String} [eq==] 键值间隔符，可选，默认 =
 * @returns {Object}
 */
export function parse(str, sep = '&', eq = '=') {
	const obj = {},
		reg = new RegExp('(?:^|\\' + sep + ')([^\\' + eq + '\\' + sep + ']+)(?:\\' + eq + '([^\\' + sep + ']*))?', 'g');

	str = (str || location.search).replace(/^[^]*\?/, '');

	let arr;
	while ((arr = reg.exec(str)) !== null) {
		if (arr[1] !== str) obj[decodeURIComponent(arr[1])] = decodeURIComponent(arr[2] || '');
	}
	return obj;
}

/**
 * 键值对转换成查询字符串
 * @param {object} query 键值对，对象
 * @returns {string} 查询参数字符串
 */
export function stringify(query) {
	const array = [];
	for (const key in query) {
		if (Object.prototype.hasOwnProperty.call(query, key)) {
			array.push([key, encodeURIComponent(query[key])].join('='));
		}
	}
	return array.join('&');
}

/**
 * 获取url的Host段，
 * @param {string} url URL地址
 * @returns {string} Host
 *
 * @example
 *
 * let url = 'http://127.0.0.1:8001/api/abc/123'
 * getHost(url) // -> http://127.0.0.1:8001/
 */
export function getHost(url) {
	const matches = url.match(hostRegex);
	if (matches) {
		return matches[0];
	}
	return '';
}

/**
 * 从url 的 path中提取参数对象，
 * @param {string} regexUrl url path规则表达式
 * @param {string} url URL
 * @returns {object} 参数键值对
 *
 * @example
 *
 * let regexUrl = '/api/:type/:id' ,
 *     url = '/api/abc/123'
 * getParams(regexUrl, url) // -> {type: 'abc', id: 123}
 *
 */
export function getParams(regexUrl, url) {
	const keys = [],
		host = getHost(regexUrl);
	// 先排除host段，因为host段的端口号与参数写法有冲突
	const regex = pathToRegexp(regexUrl.replace(host, ''), keys);
	// 排除url参数部分
	const matches = regex.exec(url.split('?')[0].replace(host, ''));
	const params = {};
	if (matches && matches.length > 0) {
		keys.forEach((key, index) => {
			params[key.name] = matches[index + 1];
		});
	}
	return params;
}

/**
 * 在url追加参数
 * @param {string} url 原本的url
 * @param {string|object} query 需要追加的参数，Object|String
 * @returns {string} 追加参数后的url
 */
export function appendQuery(url, query) {
	query = typeof query === 'string' ? parse(query) : query;
	const path = url.split('?')[0];
	const originalQuery = parse(url);
	const joinQuery = Object.assign({}, originalQuery, query);
	const queryStr = stringify(joinQuery);
	return queryStr ? [path, queryStr].join('?') : url;
}

/**
 * 通过url判断文件类型
 */
export function getFileType(fileUrl) {
	if (!fileUrl) return;

	// 后缀获取
	const suffix = fileUrl.split('.').at(-1) || '';
	// 获取类型结果
	let result = '';
	// fileUrl无后缀返回 false
	if (!suffix) {
		result = false;
		return result;
	}
	// 图片格式
	const imglist = ['png', 'jpg', 'jpeg', 'bmp', 'gif'];
	// 进行图片匹配
	result = imglist.some(function (item) {
		return item == suffix;
	});
	if (result) {
		result = 'image';
		return result;
	}
	// 匹配txt
	const txtlist = ['txt'];
	result = txtlist.some(function (item) {
		return item == suffix;
	});
	if (result) {
		result = 'txt';
		return result;
	}
	// 匹配 excel
	const excelist = ['xls', 'xlsx'];
	result = excelist.some(function (item) {
		return item == suffix;
	});
	if (result) {
		result = 'excel';
		return result;
	}
	// 匹配 word
	const wordlist = ['doc', 'docx'];
	result = wordlist.some(function (item) {
		return item == suffix;
	});
	if (result) {
		result = 'word';
		return result;
	}
	// 匹配 pdf
	const pdflist = ['pdf'];
	result = pdflist.some(function (item) {
		return item == suffix;
	});
	if (result) {
		result = 'pdf';
		return result;
	}
	// 匹配 ppt
	const pptlist = ['ppt', 'pptx'];
	result = pptlist.some(function (item) {
		return item == suffix;
	});
	if (result) {
		result = 'ppt';
		return result;
	}
	// 匹配 视频
	const videolist = ['mp4', 'm2v', 'mkv'];
	result = videolist.some(function (item) {
		return item == suffix;
	});
	if (result) {
		result = 'video';
		return result;
	}
	// 匹配 音频
	const radiolist = ['mp3', 'wav', 'wmv'];
	result = radiolist.some(function (item) {
		return item == suffix;
	});
	if (result) {
		result = 'radio';
		return result;
	}
	// 其他 文件类型
	result = 'other';
	return result;
}
